package com.shuimin.as;

import com.shuimin.as.model.sys.User;
import com.shuimin.as.service.NotificationService;
import com.shuimin.as.service.sys.SysRoles;
import com.shuimin.as.service.sys.SystemServices;
import com.shuimin.as.service.sys.UserService;
import pond.common.FILE;
import pond.common.PATH;
import pond.core.Context;
import pond.db.DB;
import pond.db.connpool.ConnectionPool;
import pond.security.ba.HttpBasicAuth;
import pond.security.jwt.HttpJwtAuth;
import pond.security.rbac.RBAC;
import pond.web.*;
import pond.web.restful.API;
import pond.web.restful.APIHandler;

import java.io.File;

/**
 * Created by Administrator on 2015/9/16.
 */
public class App {

    public static final DB DB = new DB(ConnectionPool.c3p0(FILE.loadProperties("cp.conf")));

    public static final RBAC rbac = SysRoles.init();

    public static final String LOGIN_USER = "login_user";
    public static final String LOGIN_ROLES = "login_roles";


    public static User currentUser() {
        return Session.get(((HttpCtx) Context.current()).req).get(LOGIN_USER);
    }

    public static RBAC.Roles currentRoles() {
        return Session.get(((HttpCtx) Context.current()).req).get(LOGIN_ROLES);
    }


    public static void main(String[] args) {

        HttpJwtAuth httpJwtAuth =
                //TODO move this secret to app confs
                new HttpJwtAuth("^&*)87381723721873892222hjhjsjdjjFGHJKIUYTGJ")
                        .validator((uid, pass) ->
                                        SystemServices.validateLoginUser(UserService.getUserByUid(uid), pass)
                        );
//        .onPasswordRequired((req,resp) -> {
//          resp.redirect("/login?uri=" + S._try_ret(() -> URLEncoder.encode(req.uri(),"UTF-8")));
//        });

        APIHandler auth = httpJwtAuth.auth;

        HttpBasicAuth logout = new HttpBasicAuth("system-login")
                .validator((uid, pass) -> {
                    return true;
                });

        Mid login = (req, resp) -> {
            Session.install().apply(req, resp);

            Session ses = Session.get(req);
            User user;
            if ((null == (user = ses.get(LOGIN_USER))
                    || !(((User) ses.get(LOGIN_USER))).id().equals(httpJwtAuth.user(req.ctx())))) {
                ses.set(LOGIN_USER, (user = UserService.getUserByUid(httpJwtAuth.user(req.ctx())).refineShop()));
                ses.set(LOGIN_ROLES, rbac.forUser(user.id()));
                ses.save();
            }
            if (null == ses.get(LOGIN_ROLES)) {
                ses.set(LOGIN_ROLES, rbac.forUser(user.id()));
                ses.save();
            }
        };
        Pond.init(
                p -> {
                    p.get("/login", (req, resp) -> {
                        resp.sendFile(new File(PATH.detectWebRootPath()
                                + File.separator
                                + "www"
                                + File.separator
                                + "login.html"
                        ));
                    });

                    p.post("/gettoken",
                            CtxHandler.express(Session.install()),
                            httpJwtAuth.basicSignIn("username", "password"));
                    p.get("/wscnct", CtxHandler.express(Session.install()), InternalMids.websocket(wsctx -> {
                        NotificationService.add(Session.get(wsctx), wsctx);
                        wsctx.onMessage((msg, ctx) -> {
                            ctx.sendTextFrame("recv msg: " + msg);
                        });
                        wsctx.onClose(ctx -> {
                            ctx.sendTextFrame("closing socket");
                        });
                    }));
                    p.use("/api/*",
                            auth,
                            CtxHandler.express(login),
                            new API()
                                    .use("/users/*", new USER())
                                    .use("/ranks/*", new RANK())
                                    .use("/shops/*", new SHOP())
                                    .use("/sys/*", new SYSTEM())
                                    .use("/brief/*", new BRIEF())
                                    .use("/excel/*", new EXCEL())
                                    .use("/orders/*", new REPAIR_ORDER())
                                    .use("/shop_extra/*", new SHOP_EXTRA())
                                    .use("/rbac/*", rbac.controller.get(
                                                    "/reload", (req, resp) -> {
                                                        rbac.sync(UserService.briefForRole(), SysRoles.all);
                                                        resp.send(200);
                                                    })
                                    )
                    );

                    //find the real file
                    p.get("/*", p._static("www"));
                    //send our index.html if not found since we use angular
                    p.otherwise((req, resp) -> {
                        resp.sendFile(new File(PATH.detectWebRootPath()
                                + File.separator
                                + "www"
                                + File.separator
                                + "index.html"
                        ));
                    });
                }).listen();
    }

}
